package cn.sdormitory.violative.service.imple;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONObject;
import cn.sdormitory.basedata.dao.BClassDao;
import cn.sdormitory.basedata.dao.BStudentDao;
import cn.sdormitory.basedata.entity.BClass;
import cn.sdormitory.basedata.entity.BStudent;
import cn.sdormitory.basedata.vo.BClassVo;
import cn.sdormitory.common.utils.ContainerUtil;
import cn.sdormitory.common.utils.SysUserUtils;
import cn.sdormitory.smartclass.entity.ClassDv;
import cn.sdormitory.smartclass.service.ClassDvService;
import cn.sdormitory.sys.dao.SysDeptDao;
import cn.sdormitory.sys.dao.SysUserDao;
import cn.sdormitory.sys.entity.SysUser;
import cn.sdormitory.sys.service.SysUserRoleService;
import cn.sdormitory.sys.service.SysUserService;
import cn.sdormitory.sys.vo.WechatNotifyClassTeacherInfo;
import cn.sdormitory.violative.dao.ViolationPatrolDao;
import cn.sdormitory.violative.entity.ViolationPatrol;
import cn.sdormitory.violative.enums.ViolationPatrolStatus;
import cn.sdormitory.violative.form.ViolationPatrolGoBackForm;
import cn.sdormitory.violative.form.ViolationPatrolQueryForm;
import cn.sdormitory.violative.form.ViolationPatrolReceiveForm;
import cn.sdormitory.violative.form.ViolationPatrolSaveForm;
import cn.sdormitory.violative.service.ViolationPatrolService;
import cn.sdormitory.violative.vo.ViolationPatrolReceiveInfoVo;
import cn.sdormitory.wx.entity.WechatPushMessage;
import cn.sdormitory.wx.mapper.WechatPushMessageMapper;
import cn.sdormitory.wx.utils.WXUtil;
import cn.sdormitory.wx.utils.WeatherDataCreator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ViolationPatrolServiceImpl extends ServiceImpl<ViolationPatrolDao, ViolationPatrol> implements ViolationPatrolService {
    
    @Resource
    private SysUserDao sysUserDao;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysDeptDao sysDeptDao;
    @Resource
    private ClassDvService classDvService;
    @Resource
    private SysUserService userService;
    @Resource
    private BStudentDao studentDao;
    @Resource
    private BClassDao classDao;

    @Override
    public IPage<ViolationPatrol> pageList(ViolationPatrolQueryForm queryForm) {
        QueryWrapper<ViolationPatrol> wrapper = queryForm.queryOrderByDescId();
        Page<ViolationPatrol> page = page(queryForm.generatePage(), wrapper);
        List<ViolationPatrol> records = page.getRecords();
        ContainerUtil.forEach(records, this::bindStudentNameAndClassName);
        return page;
    }

    @Override
    public ViolationPatrol getDetail(long id) {
        ViolationPatrol violationPatrol = getById(id);
        bindStudentNameAndClassName(violationPatrol);
        return violationPatrol;
    }

    private void bindStudentNameAndClassName(ViolationPatrol violationPatrol) {
        bindStudentName(violationPatrol);
        bindClassName(violationPatrol);
    }

    private void bindClassName(ViolationPatrol violationPatrol) {
        Long classId = violationPatrol.getClassId();
        if(classId != null){
            BClass bClass = classDao.selectOne(Wrappers.lambdaQuery(BClass.class)
                    .select(BClass::getClassName)
                    .eq(BClass::getId, classId));
            if(bClass != null){
                violationPatrol.setClassName(bClass.getClassName());
            }
        }
    }

    private void bindStudentName(ViolationPatrol violationPatrol) {
        Long studentId = violationPatrol.getStudentId();
        if(studentId != null){
            BStudent bStudent = studentDao.selectOne(Wrappers.lambdaQuery(BStudent.class)
                    .select(BStudent::getStudentName)
                    .eq(BStudent::getId, studentId));
            if(bStudent != null){
                violationPatrol.setStudentName(bStudent.getStudentName());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(ViolationPatrolSaveForm form) {
        List<ViolationPatrol> violationPatrols = form.generateViolationPatrols();
        for (ViolationPatrol violationPatrol : violationPatrols) {
            if(violationPatrol.getId() != null){
                updateById(violationPatrol);
            }else {
                save(violationPatrol);
            }
        }
    }

    @Override
    public void submit(long id) {
        ViolationPatrol violationPatrol = getOne(Wrappers.lambdaQuery(ViolationPatrol.class)
                .select(ViolationPatrol::getId,ViolationPatrol::getStatus)
                .eq(ViolationPatrol::getId, id));
        Assert.notNull(violationPatrol,"获取不到违纪巡查信息");
        ViolationPatrolStatus patrolStatus = ViolationPatrolStatus.CREATED;
        Assert.isTrue(Objects.equals(violationPatrol.getStatus(),patrolStatus.getValue()),
                ()-> "当前违纪巡查不为"+patrolStatus.getText()+"状态,不支持提交操作");
        violationPatrol.setStatus(ViolationPatrolStatus.SUBMIT.getValue());
        violationPatrol.initCreateAndModifyInfo();
        updateById(violationPatrol);
    }

    public void delete(long id){
        ViolationPatrol violationPatrol = getOne(Wrappers.lambdaQuery(ViolationPatrol.class)
                .select(ViolationPatrol::getId,ViolationPatrol::getStatus)
                .eq(ViolationPatrol::getId, id));
        Assert.notNull(violationPatrol,"获取不到违纪巡查信息");
        Assert.isTrue(Convert.toInt(violationPatrol.getStatus(),0)<3,"只有草稿和待接收状态才可以删除");
        removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String receive(ViolationPatrolReceiveForm receiveForm) {
        receiveForm.validThrow();
        ViolationPatrol violationPatrol = getById(receiveForm.getViolationPatrolId());
        Assert.notNull(violationPatrol,"获取不到指定违纪巡查信息");
        receiveForm.initTimeSlot(violationPatrol.getViolationTime());
        receiveForm.validStudentInfoItems(violationPatrol);
        ViolationPatrolStatus submitStatus = ViolationPatrolStatus.SUBMIT;
        ViolationPatrolStatus receiveStatus = ViolationPatrolStatus.RECEIVE;
        Assert.isTrue(Objects.equals(violationPatrol.getStatus(),submitStatus.getValue())
                || Objects.equals(violationPatrol.getStatus(),receiveStatus.getValue()),
                ()->"只有"+submitStatus.getText()+"或"+receiveStatus.getText()+"状态才能领取");
        int existStudentCount = classDvService.countByViolationPatrolId(receiveForm.getViolationPatrolId());
        if(existStudentCount + receiveForm.getViolationStudentInfos().size() > violationPatrol.getStudentNum()){
            return "最多领取"+violationPatrol.getStudentNum()+"个学生";
        }
        List<ClassDv> classDvs = receiveForm.generateClassViolations(violationPatrol);
        classDvService.addClassDvs(classDvs);
        calculationAndUpdateCompleteOrReceiveStatus(violationPatrol);
        return null;
    }

    @Override
    public List<ViolationPatrolReceiveInfoVo> getViolationPatrolReceiveInfos(long id) {
        return baseMapper.getViolationPatrolReceiveInfos(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String goBackViolationPatrol(ViolationPatrolGoBackForm goBackForm) {
        goBackForm.validThrow();
        ViolationPatrol violationPatrol = getById(goBackForm.getViolationPatrolId());
        Assert.notNull(violationPatrol,"根据违纪巡查编号找不到违纪巡查信息");
        boolean existById = classDvService.existById(goBackForm.getDvId());
        Assert.isTrue(existById,"违纪巡查里不存在该违纪学生");
        classDvService.deleteById(goBackForm.getDvId());
        calculationAndUpdateCompleteOrReceiveStatus(violationPatrol);
        return null;
    }

    private void calculationAndUpdateCompleteOrReceiveStatus(ViolationPatrol violationPatrol) {
        int existStudentCount = classDvService.countByViolationPatrolId(violationPatrol.getId());
        if(existStudentCount >= violationPatrol.getStudentNum()) {
            violationPatrol.setStatus(ViolationPatrolStatus.COMPLETE.getValue());
        }else if(existStudentCount > 0){
            violationPatrol.setStatus(ViolationPatrolStatus.RECEIVE.getValue());
        }else {
            violationPatrol.setStatus(ViolationPatrolStatus.SUBMIT.getValue());
        }
        update(Wrappers.lambdaUpdate(ViolationPatrol.class)
                .eq(ViolationPatrol::getId,violationPatrol.getId())
                .set(ViolationPatrol::getStatus,violationPatrol.getStatus())
        );
    }
    public List<BClassVo> getbClassVos(Long userId) {
        boolean isDeptManager = false ; //是否部门经理
        List<Long> roleIdList = sysUserRoleService.listRoleIdByUserId(userId);
        for (Long roleId : roleIdList) {
            if(roleId == 2) {
                isDeptManager = true ;
                break;
            }
        }
        
        List<BClassVo> classList = new ArrayList<>();
        if(isDeptManager) {
            SysUser user = sysUserDao.selectById(userId);
            List<Long> deptIds = sysDeptDao.getAllChildByParent(user.getDeptId());
            classList = classDao.getAppClassByDeptIds(deptIds);
        } else {
            // 获取班主任下所有班级
            classList = classDao.getAppClassListByTeaId(userId);
        }
        return classList;
    }
    
    @Override
    public List<Map<String, String>> getViolationPatrolStatistics(String startDate, String endDate) {
        Long userId = SysUserUtils.getSysUser().getId();
        List<BClassVo> bClassVos = getbClassVos(userId);
        List<Long> classIds = bClassVos.stream().map(BClassVo::getClassId).collect(Collectors.toList());
        
        List<ViolationPatrol> violationPatrols = baseMapper.getViolationPatrolStatistics(startDate, endDate, classIds);
        List<Map<String, String>> resultList = new ArrayList<>();
    
        if(CollectionUtil.isEmpty(violationPatrols)) {
            return resultList;
        }
        Map<Long, List<ViolationPatrol>> collect = violationPatrols.stream().collect(Collectors.groupingBy(ViolationPatrol::getClassId));
    
        for (Map.Entry<Long, List<ViolationPatrol>> entry : collect.entrySet()) {
            Long classId = entry.getKey();
            List<ViolationPatrol> violations = entry.getValue();
            
            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("classId", String.valueOf(classId));
            resultMap.put("className", violations.get(0).getClassName());
            resultMap.put("violationCount", String.valueOf(violations.size()));
            
            resultList.add(resultMap);
        }
        
        return resultList;
    }
    
    @Override
    public List<ViolationPatrol> getViolationPatrolStatisticsDetail(String startDate, String endDate, String classId) {
        List<ViolationPatrol> resultList = this.baseMapper.getViolationDetailList(startDate, endDate, classId);
        return resultList;
    }
}
